#include <stdio.h>
#include "sekai/VoiceSampler.h"
#include <sndfile.h>
#include <math.h>

class MyVoiceSampler : public VoiceSampler
{
      
      virtual bool addOnePulse();
      VoiceRecord voice;
private:
      int _samplerate=0;
      float _scaleFactor=1.0;
      float _pitchShift=1.0;
      public:
        MyVoiceSampler(int buffersize,std::string voicepath) : VoiceSampler(buffersize) {
            VoiceSampler::load(voice,_samplerate,voicepath);
        }
        int samplerate(){return _samplerate;}
        void setTimeScale(float factor) {_scaleFactor=factor;}
        void setPitchShift(float factor) {_pitchShift=factor;}
};

bool MyVoiceSampler::addOnePulse()
{
    float currentIndex = inputPositionSamples();
    currentIndex /= _scaleFactor;
    float currentTime = currentIndex / _samplerate;
   
    Pitch pmkL, pmkR;
    Pitch f0L, f0R;
    
    float f0_interp=0;
    float pmk_interp=0;
        
    int pmkIndex = findPitchMark(voice.pmkTrack,currentTime,pmkL,pmkR,&pmk_interp);
    int f0Index = findPitchMark(voice.f0Track,currentTime,f0L,f0R,&f0_interp);
    //printf("f0_interp %f\n",f0_interp);
    float input_f0 = 500;
    if(f0L.f0>0 && f0R.f0>0)
    {
        input_f0 = f0L.f0*(1-f0_interp) + f0R.f0*f0_interp;
        //printf("input_f0: %f\n",input_f0);
    }
    
    if(f0Index==-1) return false; //end of file
    
    float output_f0 = input_f0*_pitchShift;
    
    int period = _samplerate/output_f0;
    
    int posL = pmkL.pos*_samplerate;
    int posR = pmkR.pos*_samplerate;
                
    int period2 = _samplerate/input_f0*2;
    float impulse_response[period2];
    float impulse_response_L[period2];
    float impulse_response_R[period2];
    
    //if(pmk_interp>0.5) pmk_interp=1.0; else pmk_interp=0.0;
                
    for(int i=0;i<period2;i++)
    {
            if(i+posL<voice.input_data_length) impulse_response_L[i] = voice.input_data[i+posL];
            else impulse_response_L[i]=0;
            if(i+posR<voice.input_data_length) impulse_response_R[i] = voice.input_data[i+posR];
            else impulse_response_R[i]=0;
            
            impulse_response[i] = impulse_response_L[i] * (1-pmk_interp) + impulse_response_L[i]*pmk_interp;
    }
    
    VoiceSampler::hanningWindow(impulse_response,period2);
    
    //fractional delay is added here
    ola(impulse_response,period2,period);
    return true;
   
}
int main(int argc,char** argv)
{
     if(argc<3)
     {
         printf("usage: vosamp_test input.wav output.wav [timescale] [pitchshift]\n");
         return 1;
     }
     std::string voicepath=argv[1];
     std::string outfile=argv[2];
     MyVoiceSampler vosamp(8192,voicepath);
     
     if(argc>3) vosamp.setTimeScale(atof(argv[3]));
     if(argc>4) vosamp.setPitchShift(atof(argv[4]));
     
     
    SF_INFO info={0};
	info.samplerate=vosamp.samplerate();
	info.channels=1;
	info.format=SF_FORMAT_WAV | SF_FORMAT_PCM_16;
	
	SNDFILE* sf = sf_open(outfile.c_str(),SFM_WRITE,&info);
	
    while(1)
    {
        int size=1024;
        int fill=size*4;
        
        float buffer_out[size];
		if(vosamp.readData(buffer_out,size,fill)==false) break;
		sf_write_float(sf,buffer_out,size);
    }

    sf_close(sf);
}

//TODO: copyout, window function
